<?php
require_once 'Junction/Utils/Mapping.php';
require_once 'Junction/Utils/Reflection/Exception.php';

class Junction_Utils_Reflection {

	public static function getInstance($classname, array $args) {
		if (!class_exists($classname))
			throw new Junction_Utils_Reflection_Exception('The class was not defined: ' . $classname);
		$handle = new ReflectionClass($classname);
		if ($handle->getConstructor() == null)
			throw new Junction_Utils_Reflection_Exception('Class has no valid constructor');
		if ($handle->getConstructor()->getNumberOfRequiredParameters() > count($args))
			throw new Junction_Utils_Reflection_Exception('Wrong number of parameters for constructor');
		return $handle->newInstanceArgs($args);
	}
	
	public static function invokeArgs($object, $method, array $args) {
		$handle = new ReflectionObject($object);
		$methodHandle = $handle->getMethod($method);
		if ($methodHandle->getNumberOfRequiredParameters() > count($args))
			throw new Junction_Utils_Reflection_Exception('Too few arguments passed');
		return $methodHandle->invokeArgs($object, $args);
	}
	
	public static function methodExists($object, $method) {
		try {
			$handle = new ReflectionObject($object);
			$methodHandle = $handle->getMethod($method);
			return isset($methodHandle);
		} catch (ReflectionException $e) {
			throw new Junction_Utils_Reflection_Exception($e->getMessage());
		}
	}
	
	public function getValueFor($object, $property) {
		try {
			return $object->{Junction_Utils_Mapping::getGetMethodFor($property)}();
		} catch (ReflectionException $e) {
			throw new Junction_Utils_Reflection_Exception($e->getMessage());
		}
	}
	
	public function setValueFor($object, $property, $value) {
		try {
			return $object->{Junction_Utils_Mapping::getSetMethodFor($property)}($value);
		} catch (ReflectionException $e) {
			throw new Junction_Utils_Reflection_Exception($e->getMessage());
		}
	}
}
?>